/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package fi.uba.algo3.tp3.modelo.actores;

import fi.uba.algo3.tp3.modelo.servicios.ServicioJuego;
import fi.uba.algo3.tp3.vista.Observador;
import fi.uba.algo3.tp3.modelo.actores.exceptions.*;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Familia
 */
public class FantasmaCamaleon extends Fantasma {

    private static final int MAX_MOVIMIENTOS = 100;
    private Fantasma fantasma;
    private int contadorTopeMovimientos;
    private int contadorMovimientos;
    private List<Fantasma> fantasmas;
    private ServicioJuego servicio; //necesario para el metodo vivirComido

    //Este Fantasma sería el decorado, cada X movimientos pasa a ser otro tipo
    // de fantasma.
    public FantasmaCamaleon(ServicioJuego servicio, Integer distanciaDeColision) {
        super(servicio, distanciaDeColision);
        try {
            this.contadorMovimientos = 0;
            this.contadorTopeMovimientos = MAX_MOVIMIENTOS;
            this.servicio = servicio;
            this.fantasmas = new LinkedList<Fantasma>();
            instanciarFantasmas();
            cambiarFantasma();
        } catch (PosicionInvalidaException ex) {
            ex.printStackTrace();
        }
    }

    public Fantasma getFantasma() {
        return this.fantasma;
    }

    @Override
    public void reestablecer(ServicioJuego servicio) {
        fantasma.reestablecer(servicio);
    }

    @Override
    public void vivir() {
        try {
            fantasma.vivir();
            actualizarPosicion();
            revisarCambioDeFantasma();
        } catch (PosicionInvalidaException ex) {
            Logger.getLogger(FantasmaCamaleon.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    @Override
    public void setObserver(Observador observer) {
        super.setObserver(observer);
        for (Fantasma fantasmaAux : fantasmas) {
            fantasmaAux.setObserver(observer);
        }

    }

    public void instanciarFantasmas() {
        fantasmas.add(new FantasmaRapido(servicio, distanciaDeColision));
        fantasmas.add(new FantasmaBobo(servicio, distanciaDeColision));
        fantasmas.add(new FantasmaListo(servicio, distanciaDeColision));
    }

    @Override
    public void setX(int x) throws PosicionInvalidaException {
        for (Fantasma fantasmaAux : fantasmas) {
            fantasmaAux.setX(x);
        }

        super.setX(x);
    }

    @Override
    public void setY(int y) throws PosicionInvalidaException {
        for (Fantasma fantasmaAux : fantasmas) {
            fantasmaAux.setY(y);
        }

        super.setY(y);
    }

    @Override
    public void setPosicionInicialX(Integer posicionInicialX) {
        for (Fantasma fantasmaAux : fantasmas) {
            fantasmaAux.setPosicionInicialX(posicionInicialX);
        }
        super.setPosicionInicialX(posicionInicialX);
    }

    @Override
    public void setPosicionInicialY(Integer posicionInicialY) {
        for (Fantasma fantasmaAux : fantasmas) {
            fantasmaAux.setPosicionInicialY(posicionInicialY);
        }
        super.setPosicionInicialY(posicionInicialY);
    }

    @Override
    public void hayQueHuir() {
        fantasma.hayQueHuir();
    }

    @Override
    public void hayQueAtacar() {
        fantasma.hayQueAtacar();
    }

    @Override
    // No hay implementacion ya que en este release se lo delega al fantasma
    protected void vivirAtacando(ServicioJuego servicio) {
    }

    @Override
    // No hay implementacion ya que en este release se lo delega al fantasma
    protected void vivirHuyendo(ServicioJuego servicio) {
    }

    @Override
    protected Boolean hayColision(Personaje p) {
        return fantasma.hayColision(p);
    }

    @Override
    // No hay implementacion ya que en este release se lo delega al fantasma
    protected void vivirComido() {
    }

    private void revisarCambioDeFantasma() {
        try {
            if (this.contadorMovimientos < this.contadorTopeMovimientos) {
                this.contadorMovimientos++;
            } else {
                //actualizarPosicion();
                cambiarFantasma();
                regenerarTope();
                contadorMovimientos = 0;
            }
        } catch (PosicionInvalidaException ex) {
            ex.printStackTrace();
        }
    }

    private void regenerarTope() {
        double random = Math.random();
        int valor = (int) (random * (MAX_MOVIMIENTOS + 1)) + 1;
        this.contadorTopeMovimientos = valor;
    }

    private void actualizarPosicion() throws PosicionInvalidaException {
        setX(fantasma.getX());
        setY(fantasma.getY());
    }

    private void cambiarFantasma() throws PosicionInvalidaException {
        Fantasma fantasmaAux = fantasma;
        double aleatorio = (Math.random() * (fantasmas.size() - 1));
        int indice = (int) aleatorio;
        fantasma = fantasmas.get(indice);
        if (fantasmaAux != null) {
            fantasma.setEstado(fantasmaAux.getEstado());
        }
    }
}
